home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Text Editor / Source / TextEditorUtils.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-13  |  33.4 KB  |  1,270 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        TextEditorUtils.cpp
  3.  
  4.     Contains:    TextEditor utility functions & classes
  5.  
  6.     Written by:    Steve Smith
  7.  
  8.     Copyright:    © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. #ifndef _COMPILERDEFS_
  12. #include "CompDefs.h"
  13. #endif
  14.  
  15. // -- OpenDoc Utilities --
  16.  
  17. #ifndef _EXCEPT_
  18. // Exceptions define several important macros (e.g. CHECKENV)
  19. // which are used in the SOM method dispatch glue. If Except.h
  20. // is not included early enough, exceptions may not be thrown
  21. // correctly when returning from a SOM method with "ev" parameter set.
  22. #include <Except.h>
  23. #endif
  24.  
  25. // -- TextEditor Includes --
  26.  
  27. #ifndef SOM_SampleCode_TextEditor_xh
  28. #include "TextEditor.xh"
  29. #endif
  30.  
  31. #ifndef _TEXTEDITORUTILS_
  32. #include "TextEditorUtils.h"
  33. #endif
  34.  
  35. #ifndef _TEXTEDITORDEF_
  36. #include "TextEditorDef.h"
  37. #endif
  38.  
  39. #ifndef _STDTEXTPROPERTIES_
  40. #include "StdTextProps.h"
  41. #endif
  42.  
  43. #ifndef _Textension_
  44. #include "Textension.h"
  45. #endif 
  46.  
  47. // -- OpenDoc Includes --
  48.  
  49. #ifndef SOM_ODNameSpaceManager_xh
  50. #include <NmSpcMg.xh>
  51. #endif
  52.  
  53. #ifndef SOM_ODObjectNameSpace_xh
  54. #include "ObjectNS.xh"
  55. #endif
  56.  
  57. #ifndef _ODTYPES_
  58. #include <ODTypes.h>
  59. #endif
  60.  
  61. #ifndef SOM_ODPart_xh
  62. #include <Part.xh>
  63. #endif
  64.  
  65. #ifndef SOM_Module_OpenDoc_StdProps_defined
  66. #include <StdProps.xh>
  67. #endif
  68.  
  69. #ifndef SOM_ODFrame_xh
  70. #include <Frame.xh>
  71. #endif
  72.  
  73. #ifndef SOM_ODFrameFacetIterator_xh
  74. #include <FrFaItr.xh>
  75. #endif
  76.  
  77. #ifndef SOM_ODCanvas_xh
  78. #include <Canvas.xh>
  79. #endif
  80.  
  81. #ifndef SOM_ODTransform_xh
  82. #include <Trnsform.xh>
  83. #endif
  84.  
  85. #ifndef SOM_ODStorageUnit_xh
  86. #include <StorageU.xh>
  87. #endif
  88.  
  89. #ifndef SOM_ODTranslation_h
  90. #include <Translt.xh>
  91. #endif
  92.  
  93. // -- OpenDoc Utilities --
  94.  
  95. #ifndef _BNDNSUTL_
  96. #include <BndNSUtl.h>
  97. #endif
  98.  
  99. #ifndef _DOCUTILS_
  100. #include <DocUtils.h>
  101. #endif
  102.  
  103. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  104. #include <StdTypes.xh>
  105. #endif
  106.  
  107. #ifndef _INFOUTIL_
  108. #include <InfoUtil.h>
  109. #endif
  110.  
  111. #ifndef _ISOSTR_
  112. #include <ISOStr.h>
  113. #endif
  114.  
  115. #ifndef _EXCEPT_
  116. #include <Except.h>
  117. #endif
  118.  
  119. #ifndef _ODMEMORY_
  120. #include <ODMemory.h>
  121. #endif
  122.  
  123. #ifndef _PASCLSTR_
  124. #include <PasclStr.h>
  125. #endif
  126.  
  127. #ifndef _STORUTIL_    
  128. #include <StorUtil.h>
  129. #endif
  130.  
  131. #ifndef _STDTYPIO_
  132. #include <StdTypIO.h>
  133. #endif
  134.  
  135. #ifndef _USERSRCM_
  136. #include <UseRsrcM.h>
  137. #endif
  138.  
  139. #ifndef _BARRAY_
  140. #include <BArray.h>
  141. #endif
  142.  
  143. #ifndef _ODUTILS_
  144. #include <ODUtils.h>
  145. #endif
  146.  
  147. #ifndef _TEMPITER_
  148. #include <TempIter.h>
  149. #endif
  150.  
  151. #ifndef _TEMPOBJ_
  152. #include <TempObj.h>
  153. #endif
  154.  
  155. // --- Macintosh Includes ---
  156.  
  157. #ifndef __TYPES__
  158. #include <Types.h>
  159. #endif
  160.  
  161. #ifndef __EVENTS__
  162. #include <Events.h>
  163. #endif
  164.  
  165. #ifndef __RESOURCES__
  166. #include <Resources.h>
  167. #endif
  168.  
  169. #ifndef __DIALOGS__
  170. #include <Dialogs.h>
  171. #endif
  172.  
  173. #ifndef __CONTROLS__
  174. #include <Controls.h>
  175. #endif
  176.  
  177. #ifndef __WINDOWS__
  178. #include <Windows.h>
  179. #endif
  180.  
  181. #ifndef __TOOLUTILS__
  182. #include <ToolUtils.h>
  183. #endif
  184.  
  185. #ifndef __FIXMATH__
  186. #include <FixMath.h>
  187. #endif
  188.  
  189. #ifndef __FP__
  190. #include <fp.h>
  191. #endif
  192.  
  193. #ifndef __TEXTUTILS__
  194. #include <TextUtils.h>
  195. #endif
  196.  
  197. #ifndef __OSUTILS__
  198. #include <OSUtils.h>
  199. #endif
  200.  
  201. #ifndef __SCRIPT__
  202. #include <Script.h>
  203. #endif
  204.  
  205. #ifndef __FOLDERS__
  206. #include <Folders.h>
  207. #endif
  208.  
  209. #ifndef __FONTS__
  210. #include <Fonts.h>
  211. #endif
  212.  
  213.  
  214. #pragma segment TextEditorUtils
  215.  
  216. //====================================================================
  217. // Utility Functions
  218. //====================================================================
  219.  
  220. //--------------------------------------------------------------------
  221. // GetPartName
  222. //--------------------------------------------------------------------
  223.  
  224. ODIText* GetPartName(Environment* ev, ODPart* part, ODType category)
  225. {
  226.     ASSERT(part != kODNULL, kODErrIllegalNullPartInput);
  227.  
  228.     // Get the root part of the document.
  229.     ODDraft* draft = ODGetDraft(ev,part);
  230.     TempODPart rootPart = ODAcquireRootPartOfDraft(ev, draft);
  231.     
  232.     // Get the part name.
  233.     // If we can't get a valid name for the part, we generate one using
  234.     // the user visible category name of the part's category.
  235.     TempODIText partName = ODGetPOName(ev, part, kODNULL);
  236.     
  237.     // If the part is the root of the document, return the name of the file.
  238.     if ( ODObjectsAreEqual(ev, part, rootPart) )
  239.     {
  240.         ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);
  241.         TempPlatformFile file = GetPlatformFileFromContainer(ev, container);
  242.  
  243.         TempODIText fileName = file->GetName();
  244.         
  245.         // Test the file name against the part name. If the two are equivalent
  246.         // (not equal), then use the part name.
  247.         if ( !NamesAreEquivalent(ev, fileName, partName) )
  248.         {
  249.             // If the names are different, return the file name.
  250.             // (This code transfers the ODIText object to the partName tempobj)
  251.             DisposeIText(partName.DontDelete());
  252.             partName = fileName.DontDelete();
  253.         }
  254.     }
  255.     else
  256.     {
  257.         if ( partName == kODNULL || GetITextStringLength(partName) == 0 )
  258.         {
  259.             ODIText* categoryName;
  260.             ODNameSpaceManager* nsMgr = ODGetSession(ev,part)->GetNameSpaceManager(ev);
  261.             
  262.             // Get the category string from the category name space.
  263.             if ( GetUserCatFromCat(nsMgr, category, &categoryName) )
  264.             {
  265.                 // If we successfully retrieved the category user string, return it.
  266.                 // (This code transfers the ODIText object to the partName tempobj)
  267.                 DisposeIText(partName.DontDelete());
  268.                 partName = categoryName;
  269.             }
  270.             else
  271.             {
  272.     #if ODDebug
  273.                 // This should never happen. Check NMAP for errors.
  274.                 DebugStr("\pCategory NMAP bad, or Preferences corrupted.");
  275.     #else
  276.                 THROW(kODErrInvalidNSType);
  277.     #endif
  278.             }
  279.         }
  280.     }
  281.     
  282.     return partName.DontDelete();
  283. }
  284.  
  285. //--------------------------------------------------------------------
  286. // NamesAreEquivalent
  287. //--------------------------------------------------------------------
  288.  
  289. ODBoolean NamesAreEquivalent(Environment* ev, ODIText* fileName,
  290.                                         ODIText* partName)
  291. {
  292.     Str255 fileStr;
  293.     Str255 partStr;
  294.     
  295.     // If the strings are in different languages, we're done.
  296.     if ( (GetITextScriptCode(fileName) != GetITextScriptCode(partName)) ||
  297.             GetITextLangCode(fileName) != GetITextLangCode(partName) )
  298.         return kODFalse;
  299.     
  300.     GetITextPString(fileName, fileStr);
  301.     GetITextPString(partName, partStr);
  302.  
  303.     // If the string lengths are different, we're done.
  304.     if ( fileStr[0] != partStr[0] )
  305.         return kODFalse;
  306.  
  307.     // Return the Toolbox string equivalence test.
  308.     return EqualString(fileStr,partStr,kODTrue,kODTrue);
  309. }
  310.  
  311. //--------------------------------------------------------------------
  312. // GetEditorScriptLanguage
  313. //--------------------------------------------------------------------
  314.  
  315. void GetEditorScriptLanguage(Environment* ev, ODScriptCode* script,
  316.                              ODLangCode* language)
  317. {
  318.     CUsingLibraryResources res;
  319.     
  320.     Handle versHdl = Get1Resource('vers', 1);
  321.     
  322.     // Get the region code of the editor, otherwise use the
  323.     // region code the of the primary system script.
  324.     
  325.     long region;
  326.     if ( versHdl )
  327.     {
  328.         region = (long)(*(VersRecHndl) versHdl)->countryCode;
  329.         ReleaseResource(versHdl);
  330.     }
  331.     else
  332.     {
  333.         region = GetScriptManagerVariable(smRegionCode);
  334.     }
  335.     
  336.     // Spanish & Japanese are not actually supported by the editor.
  337.     // They are provided as examples of how to add recognition of
  338.     // additional regions (see Script.h for region codes).
  339.     
  340.     switch ((short) region) 
  341.     {
  342.         case verUS:
  343.             *script = smRoman;
  344.             *language = langEnglish;
  345.             break;
  346.             
  347.         case verSpain:
  348.             *script = smRoman;
  349.             *language = langSpanish;
  350.             break;
  351.             
  352.         case verJapan:
  353.             *script = smJapanese;
  354.             *language = langJapanese;
  355.             break;
  356.             
  357.         default:
  358.             *script = smRoman;
  359.             *language = langEnglish;
  360.     }                
  361. }
  362.  
  363. //--------------------------------------------------------------------
  364. // LoadThumbnail
  365. //--------------------------------------------------------------------
  366.  
  367. void LoadThumbnail(Environment* ev, Handle* thumbnail)
  368. {
  369.     if ( *thumbnail ) return;
  370.     
  371.     CUsingLibraryResources res;
  372.     *thumbnail = (Handle) GetPicture(kThumbnailPicture);
  373. }
  374.  
  375. //--------------------------------------------------------------------
  376. // TilePartWindow
  377. //--------------------------------------------------------------------
  378.  
  379. Rect TilePartWindow(Environment* ev, Rect* facetBounds, Rect* partWindowBounds)
  380. {
  381.     const short    kWindowTilingConst    = 20;
  382.     const short kLeftToRight        = 0;
  383.     const short kRightToLeft        = -1;
  384.     
  385.     // Get the direction for the primary script system running on this machine.
  386.     // (Right-to-Left or Left-to-Right)
  387.     short direction = GetSysDirection();
  388.     
  389.     // The child window should be tiled from the topLeft corner of the 
  390.     // active facet whose frame is being opened.
  391.     if ( direction == kLeftToRight )
  392.     {
  393.         // Position the window rect at the top/left corner of the facet.
  394.         OffsetRect(partWindowBounds, facetBounds->left, facetBounds->top);
  395.         // Now tile the window rect down and to the right.
  396.         OffsetRect(partWindowBounds, kWindowTilingConst, kWindowTilingConst);
  397.     }
  398.     // The child window should be tiled from the topRight corner of the 
  399.     // active facet whose frame is being opened.
  400.     else if ( direction == kRightToLeft )
  401.     {
  402.         // Position the window rect at the top/right corner of the facet.
  403.         OffsetRect(partWindowBounds, (partWindowBounds->right - facetBounds->right),
  404.                     facetBounds->top);
  405.         // Now tile the window rect down and to the left.
  406.         OffsetRect(partWindowBounds, -kWindowTilingConst, kWindowTilingConst);
  407.     }
  408.     
  409.     return *partWindowBounds;
  410. }
  411.  
  412. //--------------------------------------------------------------------
  413. // CountFacets
  414. //--------------------------------------------------------------------
  415.  
  416. ODUShort CountFacets(Environment* ev, ODFrame* frame)
  417. {
  418.     ODUShort facetCount = 0;
  419.     
  420.     TempODFrameFacetIterator ffiter(ev, frame);
  421.     ODFacet* facet = ffiter.First();
  422.     while ( ffiter.IsNotComplete() )
  423.     {
  424.         facetCount++;
  425.         facet = ffiter.Next();
  426.     }
  427.     
  428.     return facetCount;
  429. }
  430.  
  431. //------------------------------------------------------------------------------
  432. // TranslateData
  433. //------------------------------------------------------------------------------
  434.  
  435. void TranslateData( Environment* ev, ODStorageUnit* fromSU, ODStorageUnit* toSU,
  436.                     ODType translateKind, ODType desiredKind )
  437. {
  438.     ODTranslation* translation = toSU->GetSession(ev)->GetTranslation(ev); 
  439.  
  440.     // create a view of the data to translate.
  441.     fromSU->Focus(ev, kODPropContents, kODPosUndefined, translateKind, 0, kODPosUndefined);
  442.     TempODStorageUnitView fromView = fromSU->CreateView(ev);
  443.  
  444.     // create a view of the destination for the translated data.
  445.     toSU->AddProperty(ev, kODPropContents);
  446.     toSU->AddValue(ev, desiredKind);
  447.     TempODStorageUnitView toView = toSU->CreateView(ev);
  448.  
  449.     THROW_IF_ERROR(translation->TranslateView(ev, fromView, toView));
  450. }
  451.  
  452. //--------------------------------------------------------------------
  453. // GetIndFINF
  454. // (must have focused resource fork before calling)
  455. //--------------------------------------------------------------------
  456.  
  457. FINF GetIndFINF(short id, short num)
  458. {
  459.     Handle    fh;
  460.     FINF    finf;
  461.  
  462.     finf.font = systemFont;
  463.     finf.face = 0;
  464.     finf.size = 0;
  465.  
  466.     if (num > 0)
  467.         if ((fh = GetResource('finf', id)) != nil)
  468.             if (num <= *(short *)(*fh))
  469.                 finf = ((FINFPtr)((*fh) + 2))[num - 1];
  470.  
  471.     return finf;
  472. }
  473.  
  474. //--------------------------------------------------------------------
  475. // SetDialogDefaults
  476. //--------------------------------------------------------------------
  477.  
  478. void SetDialogDefaults(DialogPtr dialog, ODUShort finfID, ODUShort index)
  479. {
  480.     FINF finf;
  481.  
  482.     SetDialogDefaultItem(dialog, ok);
  483.     SetDialogCancelItem(dialog, cancel);
  484.         
  485.     if ( finfID != 0 )
  486.     {    
  487.         SetPort(dialog);
  488.         
  489.         finf = GetIndFINF(finfID, index);
  490.         
  491.         TextFont(finf.font);
  492.         TextSize(finf.size);
  493.         TextFace(finf.face);
  494.         
  495.         DialogPeek dialogPeek = (DialogPeek) dialog;
  496.         (**(dialogPeek->textH)).txFont = finf.font;
  497.         (**(dialogPeek->textH)).txSize = finf.size;
  498.         (**(dialogPeek->textH)).txFace = finf.face;
  499.         
  500.         FontInfo finfo;
  501.         GetFontInfo(&finfo);
  502.         (**(dialogPeek->textH)).lineHeight = finfo.leading + finfo.ascent + finfo.descent;
  503.         (**(dialogPeek->textH)).fontAscent = finfo.ascent;
  504.         
  505.         TECalText(dialogPeek->textH);
  506.     }
  507. }
  508.  
  509. //--------------------------------------------------------------------
  510. // FixedToIntRect
  511. //--------------------------------------------------------------------
  512.  
  513. void FixedToIntRect(ODRect& fixedRect, Rect& intRect)
  514. {
  515.     intRect.top        = FixedToInt(fixedRect.top);
  516.     intRect.left    = FixedToInt(fixedRect.left);
  517.     intRect.bottom    = FixedToInt(fixedRect.bottom);
  518.     intRect.right    = FixedToInt(fixedRect.right);
  519. }
  520.  
  521. //--------------------------------------------------------------------
  522. // IntToFixedRect
  523. //--------------------------------------------------------------------
  524.  
  525. void IntToFixedRect(Rect& intRect, ODRect& fixedRect)
  526. {
  527.     fixedRect.left        = ff(intRect.left);
  528.     fixedRect.top        = ff(intRect.top);
  529.     fixedRect.right        = ff(intRect.right);
  530.     fixedRect.bottom    = ff(intRect.bottom);
  531. }
  532.  
  533. //--------------------------------------------------------------------
  534. // LongToFixedRect
  535. //--------------------------------------------------------------------
  536.  
  537. void LongToFixedRect(TLongRect& longRect, ODRect& fixedRect)
  538. {
  539.     fixedRect.left        = ff(longRect.left);
  540.     fixedRect.top        = ff(longRect.top);
  541.     fixedRect.right        = ff(longRect.right);
  542.     fixedRect.bottom    = ff(longRect.bottom);
  543. }
  544.  
  545. //--------------------------------------------------------------------
  546. // SetMenuCommandIndString
  547. //--------------------------------------------------------------------
  548.  
  549. void SetMenuCommandIndString( Environment*    ev, 
  550.                               ODCommandID    command, 
  551.                               ODSShort        resID, 
  552.                               ODSShort        index )
  553. {
  554.     Str255 menuStr;
  555.     ODGetIndString(menuStr, resID, index);
  556.     
  557.     TempODIText menuText = CreateIText(gGlobals->fEditorsScript, 
  558.                                        gGlobals->fEditorsLanguage, 
  559.                                        menuStr);
  560.     gGlobals->fMenuBar->SetItemString(ev, command, menuText);
  561. }
  562.  
  563. //--------------------------------------------------------------------
  564. // ConvertNumberToPixels
  565. //--------------------------------------------------------------------
  566.  
  567. ODUShort ConvertNumStrToPixels(Str255 value)
  568. {
  569.     ODBoolean        metric = IsMetric();
  570.     NumberParts*    partsTable;
  571.     NumFormatString    formatRec;
  572.     Handle            itlHandle;
  573.     long            offset;
  574.     long            length;
  575.     extended80        extValue;
  576.     long double        dblValue;
  577.     Fixed            fixValue;
  578.     float            oneCentimeter = 2.54e+0;
  579.     short            result;
  580.  
  581.     GetIntlResourceTable((ScriptCode)GetScriptManagerVariable(smSysScript),
  582.                 smNumberPartsTable, &itlHandle, &offset, &length);
  583.     
  584.     HLock(itlHandle);
  585.     partsTable = (NumberPartsPtr) ((long) (*itlHandle) + offset);
  586.     
  587.     result = StringToFormatRec("\p###.##;-###.##;0", partsTable, &formatRec);
  588.  
  589.     result = StringToExtended((ConstStr255Param) value, &formatRec, partsTable, &extValue);
  590.  
  591.     DisposePtr((Ptr)partsTable);
  592.  
  593. #ifdef __powerc
  594.     x80told(&extValue, &dblValue);
  595.     fixValue = FloatToFixed(dblValue);
  596.         // convert extended80 to fixed
  597. #else
  598.     fixValue = FloatToFixed((float_t)extValue);
  599. #endif
  600.  
  601.     if ( metric ) fixValue = FixDiv(fixValue, FloatToFixed(oneCentimeter));
  602.         // convert centimeters to inches
  603.     
  604.     fixValue = FixMul(fixValue, IntToFixed(72));
  605.         // multiply inches by 72 pixels
  606.     
  607.     HUnlock(itlHandle);
  608.  
  609.     return FixedToInt(fixValue);
  610.         // return pixel value
  611. }
  612.  
  613. //--------------------------------------------------------------------
  614. // ConvertNumberToPixels
  615. //--------------------------------------------------------------------
  616.  
  617. void ConvertPixelsToNumStr(ODUShort value, Str255* numStr)
  618. {
  619.     ODBoolean        metric = IsMetric();
  620.     NumberPartsPtr    partsTable;
  621.     NumFormatString    formatRec;
  622.     Handle            itlHandle;
  623.     long            offset;
  624.     long            length;
  625.     extended80        extValue;
  626.     Fixed            fixValue;
  627.     long double        dblValue;
  628.     float            oneCentimeter = 2.54e+0;
  629.     short            result;
  630.     
  631.  
  632.     GetIntlResourceTable((ScriptCode)GetScriptManagerVariable(smSysScript),
  633.                 smNumberPartsTable, &itlHandle, &offset, &length);
  634.     
  635.     HLock(itlHandle);    
  636.     partsTable = (NumberPartsPtr)((long)(*itlHandle) + offset);
  637.     
  638.     result = StringToFormatRec("\p###.##;-###.##;0", partsTable, &formatRec);
  639.  
  640.     fixValue = FixDiv(IntToFixed(value), IntToFixed(72));
  641.         // convert pixels to inches
  642.  
  643.     if ( metric ) fixValue = FixMul(fixValue, FloatToFixed(oneCentimeter));
  644.         // convert inches to centimeters
  645.  
  646. #ifdef __powerc
  647.     extValue.man[0] = extValue.man[1] = extValue.man[2] = extValue.man[3] = extValue.man[4] = 0;
  648.     dblValue = (long double) FixedToFloat(fixValue);
  649.     ldtox80(&dblValue, &extValue);
  650.         // convert fixed value to extended80
  651. #else
  652.     extValue = 0;
  653.     extValue = (extended80) FixedToFloat(fixValue);
  654. #endif
  655.     
  656.     result = ExtendedToString(&extValue, &formatRec, partsTable, *numStr);
  657.         // create decimal string for display
  658.     
  659.     HUnlock(itlHandle);
  660. }
  661.  
  662. //-------------------------------------------------------------------------
  663. // ScrollProc
  664. //-------------------------------------------------------------------------
  665.  
  666. extern pascal void ScrollProc(ControlHandle theControl, short partCode)
  667. {
  668.  
  669.     if (partCode == 0)
  670.         return;
  671.  
  672.     ScrollDataRec* sData = (ScrollDataRec*)(**theControl).contrlRfCon;
  673.     
  674.     CTextension* textension = sData->textension;
  675.     
  676.     if ( textension == kODNULL )
  677.         return;
  678.  
  679.     Rect viewRect;
  680.     textension->GetViewRect(&viewRect);
  681.     
  682.     ODBoolean vertScrollbar = kODTrue;
  683.     if ( sData->hScrollbar == theControl )
  684.         vertScrollbar = kODFalse;
  685.     
  686.     short delta;
  687.     switch (partCode) 
  688.     {
  689.         case kControlUpButtonPart:
  690.             delta = -kSingleScrollUnit;
  691.             break;
  692.             
  693.         case kControlDownButtonPart:
  694.             delta = kSingleScrollUnit;
  695.             break;
  696.             
  697.         case kControlPageUpPart:
  698.         case kControlPageDownPart:
  699.             if ( vertScrollbar )
  700.                 delta = (viewRect.bottom - viewRect.top);
  701.             else
  702.                 delta = (viewRect.right - viewRect.left);
  703.             
  704.             if ( partCode == kControlPageUpPart )
  705.                 delta = -delta;
  706.             break;
  707.             
  708.         default:
  709.             delta = 0;
  710.     }
  711.     
  712.     short vScroll = GetControlValue(sData->vScrollbar);
  713.     short hScroll = GetControlValue(sData->hScrollbar);
  714.     
  715.     SetControlValue(theControl, GetControlValue(theControl) + delta);
  716.     
  717.     vScroll -= GetControlValue(sData->vScrollbar);
  718.     hScroll -= GetControlValue(sData->hScrollbar);    
  719.     
  720.     TLongPoint scrollAmount(hScroll, vScroll);
  721.     textension->Scroll(&scrollAmount);
  722. }
  723.  
  724. //-------------------------------------------------------------------------
  725. // ScrollProc
  726. //-------------------------------------------------------------------------
  727.  
  728. extern void ClickLoopProc(unsigned short message, void* data, void* refcon)
  729. {
  730.     if ( message == kAutoScroll)
  731.     {
  732.         TLongPoint scrollAmount = *(TLongPoint*)data;
  733.         
  734.         ScrollDataRec* sData = (ScrollDataRec*)refcon;
  735.         
  736.         SetControlValue(sData->vScrollbar, GetControlValue(sData->vScrollbar) -
  737.                                                         (short) scrollAmount.v);
  738.         SetControlValue(sData->hScrollbar, GetControlValue(sData->hScrollbar) -
  739.                                                         (short) scrollAmount.h);
  740.     }
  741. }
  742.  
  743. //-------------------------------------------------------------------------
  744. // IsNumericCharacter
  745. //-------------------------------------------------------------------------
  746.  
  747. static ODBoolean IsNumericCharacter( UInt32 charKeyCode )
  748. {
  749.     char charCode = charKeyCode & charCodeMask;
  750.     return (charCode >= 0x30 && charCode <= 0x39);
  751. }
  752.  
  753. //-------------------------------------------------------------------------
  754. // OtherDialogFilter
  755. //-------------------------------------------------------------------------
  756.  
  757. extern pascal ODBoolean OtherDialogFilter(DialogPtr dialog, EventRecord* event,
  758.                                           short* itemHit)
  759. {
  760.     ODBoolean result = kODFalse;
  761.  
  762.     if ( event->what == keyDown )    // just looking for keystrokes
  763.     {
  764.         if ( !IsNumericCharacter(event->message) )
  765.         {
  766.             char charCode = event->message & charCodeMask;
  767.             ODBoolean disallow = kODFalse;
  768.             
  769.             switch ( charCode ) 
  770.             {
  771.                 case 0x0d:    // Return
  772.                 case 0x03:    // Enter
  773.                 case 0x1b:    // Esc.
  774.                 case 0x08:    // delete key
  775.                     break;
  776.         
  777.                 case 0x2e:    // '.'
  778.                     // We need to allow command-., but disallow just '.':
  779.                     if ( (event->modifiers & cmdKey) != cmdKey ) 
  780.                         disallow = kODTrue;
  781.                     break;
  782.         
  783.                 default:
  784.                     // For all non-numeric keystrokes, beep at the user
  785.                     // and clear the event so the char is not typed.
  786.                     disallow = kODTrue;
  787.                     break;
  788.             }
  789.             
  790.             if ( disallow )
  791.             {
  792.                 // In order to disallow the entry, beep at the user
  793.                 // and clear the event so the char is not typed.
  794.                 SysBeep(1);
  795.                 event->what = nullEvent;
  796.             }
  797.         }
  798.     }
  799.     
  800.     if ( result == kODFalse )
  801.     {
  802.         // Forward other events to the standard filter-proc:    
  803.         ModalFilterUPP proc;
  804.         if ( GetStdFilterProc(&proc) == noErr )
  805.             // Call through to std filter-proc
  806.             result = CallModalFilterProc(proc, dialog, event, itemHit);    
  807.         else
  808.             WARN("Couldn't get std filter proc.");
  809.     }
  810.     
  811.     return result;
  812. }
  813.  
  814. //-------------------------------------------------------------------------
  815. // Navigation Key character codes
  816. //-------------------------------------------------------------------------
  817.  
  818. const char kKeyLeftArrow    = 0x1C;
  819. const char kKeyRightArrow    = 0x1D;
  820. const char kKeyUpArrow        = 0x1E;
  821. const char kKeyDownArrow    = 0x1F;
  822.  
  823. const char kKeyHome            = 0x01;
  824. const char kKeyEnd            = 0x04;
  825. const char kKeyPageUp        = 0x0B;
  826. const char kKeyPageDown        = 0x0C;
  827.  
  828. //-------------------------------------------------------------------------
  829. // IsArrowKey
  830. //-------------------------------------------------------------------------
  831.  
  832. static ODBoolean IsArrowKey( char charCode )
  833. {
  834.     switch ( charCode )
  835.     {
  836.         case kKeyLeftArrow:
  837.         case kKeyRightArrow:
  838.         case kKeyUpArrow:
  839.         case kKeyDownArrow:
  840.             return kODTrue;
  841.     }
  842.     
  843.     return kODFalse;
  844. }
  845.  
  846. //-------------------------------------------------------------------------
  847. // IsNavigationKey
  848. //-------------------------------------------------------------------------
  849.  
  850. static ODBoolean IsNavigationKey( char charCode )
  851. {
  852.     if ( IsArrowKey(charCode) )
  853.         return kODTrue;
  854.     
  855.     switch ( charCode )
  856.     {
  857.         case kKeyHome:
  858.         case kKeyEnd:
  859.         case kKeyPageUp:
  860.         case kKeyPageDown:
  861.             return kODTrue;
  862.     }
  863.     
  864.     return kODFalse;
  865. }
  866.  
  867. //-------------------------------------------------------------------------
  868. // KeyCausesModification
  869. //-------------------------------------------------------------------------
  870.  
  871. ODBoolean KeyCausesModification( EventRecord* event )
  872. {
  873.     // Here we are returning that any key other then a navigation key
  874.     // causes the document to be modified.
  875.  
  876.     char charCode = event->message & charCodeMask;
  877.     return !IsNavigationKey(charCode);
  878. }
  879.  
  880.  
  881. //=========================================================================
  882. // CFrameProxy
  883. //=========================================================================
  884.  
  885. //-------------------------------------------------------------------------
  886. // CFrameProxy::SetFrame
  887. //
  888. // Description:        The code will not affect the proxy fields unless it can
  889. //                     successfully acquire the incoming frame, its id, and
  890. //                    the draft the frame lives in. If something goes wrong,
  891. //                    the proxy remains unchanged.
  892. //-------------------------------------------------------------------------
  893.  
  894. void CFrameProxy::SetFrame(Environment* ev, ODFrame* frame)
  895. {
  896.     ASSERT(frame!=kODNULL, kODErrIllegalNullFrameInput);
  897.     
  898.     // Using the temp object will cleanup the incoming
  899.     // frame's refcount if something goes wrong.
  900.     frame->Acquire(ev);
  901.     TempODFrame tFrame = frame;
  902.     
  903.     // Perform all the operations that can fail, first.
  904.     TempODPart tPart = frame->AcquirePart(ev);
  905.     ODID id = frame->GetID(ev);
  906.     ODDraft* draft = ODGetDraft(ev, tPart);
  907.     ODReleaseObject(ev, fFrame);
  908.  
  909.     // If all went well, set the proxy fields.
  910.     fFrame = tFrame.DontRelease();
  911.     fID = id;
  912.     fDraft = draft;
  913. }
  914.  
  915. //-------------------------------------------------------------------------
  916. // CFrameProxy::GetFrame
  917. //-------------------------------------------------------------------------
  918.  
  919. ODFrame* CFrameProxy::GetFrame(Environment* ev)
  920. {
  921.     if ( fFrame == kODNULL )
  922.     {
  923.         TRY
  924.             TempODFrame frame = fDraft->AcquireFrame(ev, fID);
  925.             this->SetFrame(ev,frame);
  926.         CATCH_ALL
  927.             fFrame = kODNULL;
  928.             fID = kODNULLID;
  929.         ENDTRY
  930.     }
  931.     return fFrame;
  932. }
  933.  
  934. //-------------------------------------------------------------------------
  935. // CFrameProxy::FrameIsLoaded
  936. //-------------------------------------------------------------------------
  937.  
  938. ODBoolean CFrameProxy::FrameIsLoaded(Environment* ev)
  939. {
  940.     ODBoolean loaded = (fFrame != kODNULL ||
  941.                         fDraft->IsValidID(ev, fID));
  942.     return loaded;
  943. }
  944.  
  945. //-------------------------------------------------------------------------
  946. // CFrameProxy::Purge
  947. //-------------------------------------------------------------------------
  948.  
  949. void CFrameProxy::Purge(Environment* ev)
  950. {
  951.     if ( fFrame != kODNULL )
  952.     {
  953.         fID = fFrame->GetID(ev);
  954.         ODReleaseObject(ev, fFrame);
  955.     }
  956. }
  957.  
  958. //=========================================================================
  959. // CFrameInfo
  960. //=========================================================================
  961.  
  962. //-------------------------------------------------------------------------
  963. // CFrameInfo::CFrameInfo
  964. //-------------------------------------------------------------------------
  965.  
  966. CFrameInfo::CFrameInfo(ODSession* session)
  967. {
  968.     fSession = session;
  969.     fFrameActive = kODFalse;
  970.     fFrameReactivate  = kODFalse;
  971.     fShouldDisposeWindow = kODFalse;
  972.     fActiveFacet = kODNULL;
  973.     fSourceFrame = kODNULL;
  974.     fDependentFrame = kODNULL;
  975.     fPartWindowID = kODNULLID; 
  976. }
  977.  
  978. //-------------------------------------------------------------------------
  979. // CFrameInfo::~CFrameInfo
  980. //-------------------------------------------------------------------------
  981.  
  982. CFrameInfo::~CFrameInfo()
  983. {
  984.     // Deleting the proxies will release the encapsulated frames.
  985.     ODDeleteObject(fDependentFrame);
  986.     ODDeleteObject(fSourceFrame);
  987. }
  988.  
  989. //-------------------------------------------------------------------------
  990. // CFrameInfo::Externalize
  991. //-------------------------------------------------------------------------
  992.  
  993. void CFrameInfo::Externalize(Environment* ev, ODStorageUnitView* storageUnitView)
  994. {
  995.     // This method assumes that OpenDoc has passed us a storageUnitView
  996.     // that is focused to a property, but no particular value.
  997.     
  998.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  999.  
  1000.     this->CleanseFrameInfoProperty(ev, storageUnit);
  1001.     this->ExternalizeFrameInfo(ev, storageUnit, kODNULLKey, kODNULL);
  1002. }
  1003.  
  1004. //-------------------------------------------------------------------------
  1005. // CFrameInfo::CleanseFrameInfoProperty
  1006. //-------------------------------------------------------------------------
  1007.  
  1008. void CFrameInfo::CleanseFrameInfoProperty(Environment* ev, ODStorageUnit* storageUnit)
  1009. {
  1010.     ODULong numValues;
  1011.     ODULong index;
  1012.         
  1013.     numValues = storageUnit->CountValues(ev);
  1014.     
  1015.     for (index = numValues; index >= 1; index--)
  1016.     {
  1017.         // Index, from 1 to n, through the values.
  1018.         storageUnit->Focus(ev, kODNULL, kODPosSame, 
  1019.                                 kODNULL, index, kODPosUndefined);
  1020.                                 
  1021.         // Get the ISO type name for the value. The temp object
  1022.         // will automatically delete the returned value when this
  1023.         // scope is exited.
  1024.         TempODValueType value = storageUnit->GetType(ev);
  1025.         
  1026.         // If the value type is not one we support, remove it.
  1027.         if ( !ODISOStrEqual(value, kTextEditorPartInfo) )
  1028.             storageUnit->Remove(ev);
  1029.     }
  1030. }
  1031.  
  1032. //-------------------------------------------------------------------------
  1033. // CFrameInfo::ExternalizeFrameInfo
  1034. //-------------------------------------------------------------------------
  1035.  
  1036. void CFrameInfo::ExternalizeFrameInfo(Environment* ev, ODStorageUnit* storageUnit,
  1037.                                         ODDraftKey key, ODFrame* scopeFrame)
  1038. {
  1039.     // This method behaves much the same way as the ExternalizeStateInfo
  1040.     // method.
  1041.     
  1042.     if ( storageUnit->Exists(ev, kODNULL, kTextEditorPartInfo, 0) )
  1043.     {
  1044.         // Persistent object references are stored in a side table, rather than
  1045.         // in the property/value stream. Thus, deleting the contents of a value
  1046.         // will not "delete" the references previously written to that value. To
  1047.         // completely "delete" all references written to the value, we must
  1048.         // remove the value and add it back.
  1049.  
  1050.         storageUnit->Focus(ev, kODNULL, kODPosSame, kTextEditorPartInfo, 0, kODPosUndefined);
  1051.         storageUnit->Remove(ev);
  1052.     }
  1053.  
  1054.     // Add a value to write the data into.
  1055.     storageUnit->AddValue(ev, kTextEditorPartInfo);
  1056.     
  1057.     // Write a weak reference to our source frame.
  1058.     {
  1059.         ODStorageUnitRef weakRef = {0,0,0,0};
  1060.         
  1061.         if ( fSourceFrame )
  1062.         {
  1063.             ODID        frameID = fSourceFrame->GetID();
  1064.             ODID        scopeFrameID = ( scopeFrame ? scopeFrame->GetID(ev) : kODNULLID );
  1065.             ODDraft*    fromDraft = fSourceFrame->GetDraft();
  1066.     
  1067.             // If a draft key exists, then we are being cloned to another draft.
  1068.             // We must "weak" clone our display frame and reference the cloned
  1069.             // frame. The part re-uses the frameID variable so there aren't two
  1070.             // different GetWeakStorageUnitRef calls.
  1071.             if ( key )
  1072.                 frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  1073.             
  1074.             // Write out weak references to each of the part's display frames.
  1075.             storageUnit->GetWeakStorageUnitRef(ev, frameID, weakRef);
  1076.         }
  1077.         StorageUnitSetValue(storageUnit, ev, sizeof(ODStorageUnitRef), (ODPtr)&weakRef);
  1078.     }
  1079.  
  1080.     // Write a weak reference to our dependent frame.
  1081.     {
  1082.         ODStorageUnitRef weakRef = {0,0,0,0};
  1083.         
  1084.         if ( fDependentFrame )
  1085.         {
  1086.             ODID        frameID = fDependentFrame->GetID();
  1087.             ODID        scopeFrameID = ( scopeFrame ? scopeFrame->GetID(ev) : kODNULLID );
  1088.             ODDraft*    fromDraft = fDependentFrame->GetDraft();
  1089.     
  1090.             // If a draft key exists, then we are being cloned to another draft.
  1091.             // We must "weak" clone our display frame and reference the cloned
  1092.             // frame. The part re-uses the frameID variable so there aren't two
  1093.             // different GetWeakStorageUnitRef calls.
  1094.             if ( key )
  1095.                 frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  1096.             
  1097.             // Write out weak references to each of the part's display frames.
  1098.             storageUnit->GetWeakStorageUnitRef(ev, frameID, weakRef);
  1099.         }
  1100.         StorageUnitSetValue(storageUnit, ev, sizeof(ODStorageUnitRef), (ODPtr)&weakRef);
  1101.     }
  1102. }
  1103.  
  1104. //-------------------------------------------------------------------------
  1105. // CFrameInfo::CloneInto
  1106. //-------------------------------------------------------------------------
  1107.  
  1108. void CFrameInfo::CloneInto(Environment *ev, ODDraftKey key,
  1109.                             ODStorageUnitView* storageUnitView, ODFrame* scopeFrame)
  1110. {
  1111.     // This method assumes that OpenDoc has passed us a storageUnitView
  1112.     // that is focused to a property, but no particular value.
  1113.     
  1114.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  1115.  
  1116.     if ( storageUnit->Exists(ev, kODNULL, kTextEditorPartInfo, 0) == kODFalse )
  1117.     {
  1118.         this->ExternalizeFrameInfo(ev, storageUnit, key, scopeFrame);
  1119.     }
  1120. }
  1121.  
  1122. //-------------------------------------------------------------------------
  1123. // CFrameInfo::InitFromStorage
  1124. //------------------------------------------------------------------------------
  1125.  
  1126. void CFrameInfo::InitFromStorage(Environment* ev, ODStorageUnitView* storageUnitView)
  1127. {
  1128.     // This method assumes that OpenDoc has passed us a storageUnitView
  1129.     // that is focused to a property, but no particular value.
  1130.     
  1131.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  1132.  
  1133.     if ( storageUnit->Exists(ev, kODNULL, kTextEditorPartInfo, 0) )
  1134.     {
  1135.         TRY
  1136.             storageUnit->Focus(ev, kODNULL, kODPosSame,
  1137.                                kTextEditorPartInfo, 0 , kODPosUndefined);
  1138.     
  1139.             ODStorageUnitRef weakRef = {0,0,0,0};
  1140.             StorageUnitGetValue(storageUnit, ev, sizeof(ODStorageUnitRef),
  1141.                                 (ODPtr)&weakRef);
  1142.             
  1143.             if ( storageUnit->IsValidStorageUnitRef(ev, weakRef) )
  1144.             {
  1145.                 // Convert the reference into a runtime id.
  1146.                 ODID frameID = storageUnit->GetIDFromStorageUnitRef(ev, weakRef);
  1147.  
  1148.                 // Create a proxy class to support the lazy internalization.
  1149.                 CFrameProxy* proxy = new CFrameProxy;
  1150.                 proxy->InitFrameProxy(frameID, ODGetDraft(ev,storageUnit));
  1151.  
  1152.                 // Store the proxy source frame.
  1153.                 fSourceFrame = proxy;
  1154.             }
  1155.             
  1156.         CATCH_ALL
  1157.             ODDeleteObject(fSourceFrame);
  1158.             fSourceFrame = kODNULL;
  1159.         ENDTRY
  1160.  
  1161.         TRY
  1162.             ODStorageUnitRef weakRef = {0,0,0,0};
  1163.             StorageUnitGetValue(storageUnit, ev, sizeof(ODStorageUnitRef),
  1164.                                 (ODPtr)&weakRef);
  1165.             
  1166.             if ( storageUnit->IsValidStorageUnitRef(ev, weakRef) )
  1167.             {
  1168.                 // Convert the reference into a runtime id.
  1169.                 ODID frameID = storageUnit->GetIDFromStorageUnitRef(ev, weakRef);
  1170.  
  1171.                 // Create a proxy class to support the lazy internalization.
  1172.                 CFrameProxy* proxy = new CFrameProxy;
  1173.                 proxy->InitFrameProxy(frameID, ODGetDraft(ev,storageUnit));
  1174.  
  1175.                 // Store the proxy dependent frame.
  1176.                 fDependentFrame = proxy;
  1177.             }
  1178.             
  1179.         CATCH_ALL
  1180.             ODDeleteObject(fDependentFrame);
  1181.             fDependentFrame = kODNULL;
  1182.         ENDTRY
  1183.     }
  1184. }
  1185.  
  1186. //-------------------------------------------------------------------------
  1187. // CFrameInfo::SetSourceFrame
  1188. //-------------------------------------------------------------------------
  1189.  
  1190. void CFrameInfo::SetSourceFrame(Environment* ev, ODFrame* frame)
  1191. {
  1192.     if ( frame != kODNULL )
  1193.     {
  1194.         // Create a proxy class to support the lazy internalization.
  1195.         CFrameProxy* proxy = new CFrameProxy;
  1196.         proxy->InitFrameProxy(ev,frame);
  1197.         
  1198.         // Store the proxy source frame after clearing the old one.
  1199.         ODDeleteObject(fSourceFrame);
  1200.         fSourceFrame = proxy;
  1201.     }
  1202. }
  1203.  
  1204. //-------------------------------------------------------------------------
  1205. // CFrameInfo::ReleaseSourceFrame
  1206. //-------------------------------------------------------------------------
  1207.  
  1208. void CFrameInfo::ReleaseSourceFrame(Environment* ev)
  1209. {
  1210.     ODDeleteObject(fSourceFrame);
  1211. }
  1212.  
  1213. //-------------------------------------------------------------------------
  1214. // CFrameInfo::SetDependentFrame
  1215. //-------------------------------------------------------------------------
  1216.  
  1217. void CFrameInfo::SetDependentFrame(Environment* ev, ODFrame* frame)
  1218. {
  1219.     if ( frame != kODNULL )
  1220.     {
  1221.         // Create a proxy class to support the lazy internalization.
  1222.         CFrameProxy* proxy = new CFrameProxy;
  1223.         proxy->InitFrameProxy(ev,frame);
  1224.         
  1225.         // Store the proxy dependent frame after clearing the old one.
  1226.         ODDeleteObject(fDependentFrame);
  1227.         fDependentFrame = proxy;
  1228.     }
  1229. }
  1230.  
  1231. //-------------------------------------------------------------------------
  1232. // CFrameInfo::ReleaseDependentFrame
  1233. //-------------------------------------------------------------------------
  1234.  
  1235. void CFrameInfo::ReleaseDependentFrame(Environment* ev)
  1236. {
  1237.     ODDeleteObject(fDependentFrame);
  1238. }
  1239.  
  1240. //-------------------------------------------------------------------------
  1241. // CFrameInfo::AcquirePartWindow
  1242. //-------------------------------------------------------------------------
  1243.  
  1244. ODWindow* CFrameInfo::AcquirePartWindow(Environment* ev)
  1245. {
  1246.     ODWindow* window = kODNULL;
  1247.     
  1248.     if ( fPartWindowID )
  1249.     {
  1250.         window = fSession->GetWindowState(ev)->AcquireWindow(ev, fPartWindowID);
  1251.         if ( !window ) 
  1252.             fPartWindowID = kODNULLID;
  1253.     }
  1254.     
  1255.     return window;
  1256. }
  1257.  
  1258. //-------------------------------------------------------------------------
  1259. // CFrameInfo::SetPartWindow
  1260. //-------------------------------------------------------------------------
  1261.  
  1262. void CFrameInfo::SetPartWindow(Environment* ev, ODWindow* window)
  1263. {
  1264.     fPartWindowID = window ? window->GetID(ev) : kODNULLID;
  1265. }
  1266.  
  1267.  
  1268.  
  1269.  
  1270.